﻿// <com.woyouqiu.Copyright>
// --------------------------------------------------------------
// <copyright>上海有求网络科技有限公司 2015</copyright>
// <Solution>Vecen.BangChuang</Solution>
// <Project>Vecen.BangChuang.Application</Project>
// <FileName>PromotionAppService.cs</FileName>
// <CreateTime>2017-06-05 22:55</CreateTime>
// <Author>何苗</Author>
// <Email>hemiao@woyouqiu.com</Email>
// <log date="2017-06-05 22:55" version="00001">创建</log>
// --------------------------------------------------------------
// </com.woyouqiu.Copyright>

using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Abp.Application.Services;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Collections.Extensions;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Abp.Runtime.Session;
using Abp.UI;
using Vecen.BangChuang.BangChuang.Areas;
using Vecen.BangChuang.BangChuang.Common;
using Vecen.BangChuang.BangChuang.Common.Dtos;
using Vecen.BangChuang.BangChuang.DomainServices.Agents;
using Vecen.BangChuang.BangChuang.DomainServices.Common;
using Vecen.BangChuang.BangChuang.Promotions.Dtos;

namespace Vecen.BangChuang.BangChuang.Promotions {

    /// <summary>
    /// 推广相关操作
    /// </summary>
    [AbpAuthorize()]
    public class PromotionAppService: BangChuangAppServiceBase, IPromotionAppService {
        private readonly IRepository<Promotion> _promotionRepository;
        private readonly CityDomainService _cityDomainService;
        private readonly AgentDomainService _agentDomainService;
        private readonly CounterDomainService _counterDomainService;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="promotionRepository"></param>
        /// <param name="cityDomainService"></param>
        /// <param name="agentDomainService"></param>
        /// <param name="counterDomainService"></param>
        public PromotionAppService(IRepository<Promotion> promotionRepository,
            CityDomainService cityDomainService,
            AgentDomainService agentDomainService,
            CounterDomainService counterDomainService) {
            _promotionRepository = promotionRepository;
            _cityDomainService = cityDomainService;
            _agentDomainService = agentDomainService;
            _counterDomainService = counterDomainService;
        }

        /// <summary>
        /// 后台获取推广对象列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<PromotionListForAdminOutDto>> GetPromotionsForAdminAsync(
            PromotionConditionForAdminInputDto input) {
            var areaCode = _cityDomainService.GetAreaId(input);
            var query = _promotionRepository.GetAll()
                .WhereIf(input.PromotionStatus.HasValue, c => c.PromotionStatus == input.PromotionStatus.ToString())
                .WhereIf(areaCode.HasValue, c => c.AreaCode.ToString().StartsWith(areaCode.ToString()))
                .WhereIf(!input.UniversityName.IsNullOrWhiteSpace(),
                    c => c.UniversityName.Contains(input.UniversityName)
                         || c.CollegeName.Contains(input.UniversityName))
                .WhereIf(!input.Keyword.IsNullOrWhiteSpace(),
                    c => c.Name.Contains(input.Keyword) || c.Description.Contains(input.Keyword))
                .OrderBy(input.Sorting);
            var total = await Task.Run(() => query.Count());
            var entities = await Task.Run(() => query.PageBy(input).ToList());
            List<PromotionListForAdminOutDto> dtos = new List<PromotionListForAdminOutDto>();
            foreach(var promotion in entities) {
                var dto = promotion.MapTo<PromotionListForAdminOutDto>();
                dto.HeaderImageId =
                    await AttachmentManager.GetIdAsync(Promotion.PromotionHeaderAttachmentType, promotion.Id);
                dto.Address = await _cityDomainService.GetFullAddressDtoByCityId(promotion.AreaCode);
                dto.ClickCount = await _counterDomainService.GetCountAsync(CounterType.Promotion.Click, promotion.Id);
                dto.ForwardedCount =
                    await _counterDomainService.GetCountAsync(CounterType.Promotion.Forwarded, promotion.Id);
                dtos.Add(dto);
            }
            return new PagedResultDto<PromotionListForAdminOutDto>(total, dtos);
        }

        /// <summary>
        /// App获取推广对象列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<PromotionListOutDto>> GetPromotionsAsync(PromotionConditionInputDto input) {
            var userType = UserType.GeneralUser;
            var areaCode = (await UserManager.GetUserByIdAsync(AbpSession.GetUserId())).AreaCode;
            var universityName = (await UserManager.GetUserByIdAsync(AbpSession.GetUserId())).UniversityName;
            var agent = await _agentDomainService.GetByUserIdAsync(AbpSession.GetUserId());
            if(agent != null) {
                userType = agent.UserType;
                areaCode = agent.AreaCode;
                universityName = agent.UniversityName;
            }
            var query = _promotionRepository.GetAll()
                .Where(c => c.ShowForUserTypes.Contains("userType") )
                .Where(c => c.AreaCode == areaCode || c.UniversityName == universityName)
                .Where(c => c.PromotionStatus == PromotionStatus.PutOn.ToString())
                .WhereIf(!input.Keyword.IsNullOrWhiteSpace(),
                    c => c.Name.Contains(input.Keyword) || c.Description.Contains(input.Keyword));
            var total = await Task.Run(() => query.Count());
            var entities = await Task.Run(() => query.OrderBy(input.Sorting).PageBy(input).ToList());

            var dtos = new List<PromotionListOutDto>();
            foreach(var promotion in entities) {
                var dto = promotion.MapTo<PromotionListOutDto>();
                dto.HeaderImageId =
                    await AttachmentManager.GetIdAsync(Promotion.PromotionHeaderAttachmentType, promotion.Id);
                dtos.Add(dto);
            }
            return new PagedResultDto<PromotionListOutDto>(total, dtos);
        }

        /// <summary>
        /// 保存推广对象
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SavePromotionAsync(PromotionInputDto input) {
            var entity = input.MapTo<Promotion>();
            entity.AreaCode = _cityDomainService.GetAreaIdNotNull(input);
            entity.ShowForUserTypes = input.ShowForUserTypes.JoinAsString(",");
            var id = await _promotionRepository.InsertOrUpdateAndGetIdAsync(entity);

            await AttachmentManager.UpdateObjectIdAsync(Promotion.PromotionHeaderAttachmentType, input.AttachmentIds,
                id);
            await AttachmentManager.DelAttachmentAsync(Promotion.PromotionHeaderAttachmentType, input.DelAttachmentIds);
        }

        /// <summary>
        /// 获得待编辑推广对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<PromotionInputDto> GetPromotionInputDtoForEditAsync(int id) {
            var entity = await _promotionRepository.FirstOrDefaultAsync(id);
            if(entity == null) {
                throw new UserFriendlyException("请求出错!", "推广信息已不存在!");
            }

            var inputDto = new PromotionInputDto();
            inputDto.Name = entity.Name;
            inputDto.AttachmentIds = await AttachmentManager.GetIdsAsync(Promotion.PromotionHeaderAttachmentType, id);
            inputDto.ClickPrice = entity.ClickPrice;
            var cityInfo = await _cityDomainService.GetFullAddressByCityId(entity.AreaCode);
            inputDto.CityId = cityInfo?.CityId;
            inputDto.CollegeName = entity.CollegeName;
            inputDto.Description = entity.Description;
            inputDto.DistrictId = cityInfo?.DistrictId;
            inputDto.GraphicContent = entity.GraphicContent;
            inputDto.InnerClickPrice = entity.InnerClickPrice;
            inputDto.ProvinceId = cityInfo?.ProvinceId;
            inputDto.PutOnPrice = entity.PutOnPrice;
            inputDto.ShowForUserTypes = entity.ShowForUserTypes.Split(",");
            inputDto.PutOnTimeLimit = entity.PutOnTimeLimit;
            inputDto.UniversityName = entity.UniversityName;
            inputDto.Id = entity.Id;
            return inputDto;
        }

        /// <summary>
        /// 获得推广对象详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<PromotionOutDto> GetPromotionAsync(int id) {
            var entity = await _promotionRepository.FirstOrDefaultAsync(id);
            if(entity == null || entity.PromotionStatus != PromotionStatus.PutOn.ToString()) {
                throw new UserFriendlyException("请求失败", "信息已不存在!");
            }
            return entity.MapTo<PromotionOutDto>();
        }

        /// <summary>
        /// 下架
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task OffTheShelfAsync(int id) {
            var entity = await _promotionRepository.FirstOrDefaultAsync(id);
            if(entity == null) {
                throw new UserFriendlyException("请求失败", "信息已不存在!");
            }

            entity.PromotionStatus = PromotionStatus.Discarded.ToString();
            await _promotionRepository.UpdateAsync(entity);
        }

        /// <summary>
        /// 上架
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task OnTheShelfAsync(int id) {
            var entity = await _promotionRepository.FirstOrDefaultAsync(id);
            if(entity == null) {
                throw new UserFriendlyException("请求失败", "信息已不存在!");
            }

            entity.PromotionStatus = PromotionStatus.PutOn.ToString();
            await _promotionRepository.UpdateAsync(entity);
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task DeletePromotionAsync(int id) {
            await _promotionRepository.DeleteAsync(id);
        }

        /// <summary>
        /// 获得分享内容
        /// </summary>
        /// <param name="promotionId"></param>
        /// <returns></returns>
        public async Task<ShareModel> GetShareModelByIdAsync(int promotionId) {
            var promotion = await _promotionRepository.FirstOrDefaultAsync(promotionId);
            if(promotion == null) {
                throw new UserFriendlyException("获得分享信息出错!", "推广信息已被删除!");
            }
            var shareModel = new ShareModel();
            shareModel.Description = promotion.Description;
            shareModel.ImgUrl = RequestInfo.HostBaseUri + "/file/download/"
                                + (await AttachmentManager.GetIdAsync(Promotion.PromotionHeaderAttachmentType,
                                    promotionId));
            shareModel.Title = promotion.Name;
            shareModel.Link = RequestInfo.HostBaseUri + "/micro/promotion?id=" + promotionId;
            return shareModel;
        }

        /// <summary>
        /// 分享成功回调
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task ForwardedSuccessCallback(ShareSuccessInputDto input) {
            await _counterDomainService.RecordForwardedAsync(CounterType.Promotion.Forwarded, input.ObjectId,
                input.ShareType);
        }

        /// <summary>
        /// 点击成功回调(增加点击量)
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [RemoteService(false)]
        public async Task ClickSuccessCallback(int id) {
            await _counterDomainService.RecordAsync(CounterType.Promotion.Click, id);
        }
    }
}